/**
 * elancom Corporation copy right 2012 - 2015  
 *   
 * $Header: https://192.168.1.224/svn/elancom/product/elancom-platform/trunk/src/main/java/com/elancom/framework/commons/json/serializer/ObjectFieldSerializer.java 1034 2012-07-02 03:09:12Z lanzhouxue $
 * $Id: ObjectFieldSerializer.java 1034 2012-07-02 03:09:12Z lanzhouxue $
 * $Author: lanzhouxue $
 * $Date: 2012-07-02 11:09:12 +0800 (Mon, 02 Jul 2012) $
 * $Revision: 1034 $
 */
package com.elancom.framework.commons.json.serializer;

import java.util.Collection;

import com.elancom.framework.commons.json.annotation.JSONField;
import com.elancom.framework.commons.json.util.FieldInfo;

/**
 * @author elancom
 */
public class ObjectFieldSerializer extends FieldSerializer {

	private ObjectSerializer fieldSerializer;

	private Class<?> runtimeFieldClass;
	private String format;
	private boolean writeNumberAsZero = false;
	boolean writeNullStringAsEmpty = false;
	boolean writeNullBooleanAsFalse = false;
	boolean writeNullListAsEmpty = false;
	boolean writeEnumUsingToString = false;

	public ObjectFieldSerializer(FieldInfo fieldInfo) {
		super(fieldInfo);

		final JSONField annotation = fieldInfo.getAnnotation(JSONField.class);

		if (annotation != null) {
			format = annotation.format();

			if (format.trim().length() == 0) {
				format = null;
			}

			for (final SerializerFeature feature : annotation.serialzeFeatures()) {
				if (feature == SerializerFeature.WriteNullNumberAsZero) {
					writeNumberAsZero = true;
				} else if (feature == SerializerFeature.WriteNullStringAsEmpty) {
					writeNullStringAsEmpty = true;
				} else if (feature == SerializerFeature.WriteNullBooleanAsFalse) {
					writeNullBooleanAsFalse = true;
				} else if (feature == SerializerFeature.WriteNullListAsEmpty) {
					writeNullListAsEmpty = true;
				} else if (feature == SerializerFeature.WriteEnumUsingToString) {
					writeEnumUsingToString = true;
				}
			}
		}
	}

	@Override
	public void writeProperty(JSONSerializer serializer, Object propertyValue) throws Exception {
		writePrefix(serializer);

		if (format != null) {
			serializer.writeWithFormat(propertyValue, format);
			return;
		}

		if (fieldSerializer == null) {

			if (propertyValue == null) {
				runtimeFieldClass = getMethod().getReturnType();
			} else {
				runtimeFieldClass = propertyValue.getClass();
			}

			fieldSerializer = serializer.getObjectWriter(runtimeFieldClass);
		}

		if (propertyValue == null) {
			if (writeNumberAsZero && Number.class.isAssignableFrom(runtimeFieldClass)) {
				serializer.getWriter().write('0');
				return;
			} else if (writeNullStringAsEmpty && String.class == runtimeFieldClass) {
				serializer.getWriter().write("\"\"");
				return;
			} else if (writeNullBooleanAsFalse && Boolean.class == runtimeFieldClass) {
				serializer.getWriter().write("false");
				return;
			} else if (writeNullListAsEmpty && Collection.class.isAssignableFrom(runtimeFieldClass)) {
				serializer.getWriter().write("[]");
				return;
			}

			// FIX:ELANCOM
			// 空则不再继续解析
			serializer.getWriter().write("null");
			// 原代码:fieldSerializer.write(serializer, null, fieldInfo.getName(), null);
			return;
		}

		if (writeEnumUsingToString == true && runtimeFieldClass.isEnum()) {
			serializer.getWriter().writeString(((Enum<?>) propertyValue).name());
			return;
		}

		final Class<?> valueClass = propertyValue.getClass();
		if (valueClass == runtimeFieldClass) {
			fieldSerializer.write(serializer, propertyValue, fieldInfo.getName(), fieldInfo.getFieldType());
			return;
		}

		final ObjectSerializer valueSerializer = serializer.getObjectWriter(valueClass);
		valueSerializer.write(serializer, propertyValue, fieldInfo.getName(), null);
	}

}
